﻿using GenericDemo.UserCode;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text.Json;
using System.Xml.Schema;

namespace GenericDemo
{

    /// <summary>
    /// 泛型。 包括泛型类，泛型方法，泛型接口，泛型委托
    /// 简单：理解和使用泛型
    /// 中等：编写泛型类，方法，接口和委托
    /// 高级：裂解逆变和协变
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            Simple();
            //Middle();
            Advanced();
        }

        #region simple
        public static void Simple()
        {
            //没有泛型以前
            ArrayList al = new ArrayList();
            al.Add(1);
            al.Add("adsf");

            //有泛型之后
            List<int> a2 = new List<int>();
            a2.Add(1);
            //a2.Add("asdf"); 错误


            //IEnumerable和yield return的使用
            IEnumerable<int> a = GetNext10(4);
            foreach (var item in a)
            {
                Console.WriteLine(item);
            }


            //匿名类
            var ccc = new
            {
                a1 = 1,
                a2 = "abc"
            };

            //匿名类转成匿名类数组
            var b = Change(new
            {
                a1 = 1,
                a2 = "abc"
            }).ToList();

            //.net自带的实现匿名类数组的方法
            var c = Enumerable.Repeat(new
            {
                a1 = 1,
                a2 = "abc"
            }, 0);

            b.Add(new
            {
                a1 = 2,
                a2 = "222"
            });
            b.Add(new
            {
                a1 = 3,
                a2 = "333"
            });

            foreach (var item in b)
            {
                Console.WriteLine(item.a1 + "," + item.a2);
            }

            Action<string, int> act = (a, b) =>
            {
                var c = a + b;
                Console.WriteLine(c);
            };

            act?.Invoke("123", 3);

            Func<string, int> fun = (a) =>
            {
                return a.Length;
            };
            var l = fun?.Invoke("abcd");
            Console.WriteLine(l);

            Console.WriteLine("泛型！！！");

        }

        public static IEnumerable<int> GetNext10(int start)
        {
            for(int i = 1; i <= 10; i++)
            {
                yield return start+i;
            }
        }

        public static IEnumerable<T> Change<T>(T input)
        {
            yield break;
        }
        #endregion

        #region middle
        public static void Middle()
        {
            School s = new School();
            s.ID = "111";

            Major m = new Major();
            m.ID = 2;

            SchoolCRUDVM vm = new SchoolCRUDVM();
            vm.Entity = s;
            vm.DoDelete();

            MajorCRUDVM vm2 = new MajorCRUDVM();
            vm2.Entity = m;

            var test = GetEntity(vm);
            Console.WriteLine(JsonSerializer.Serialize(test));

            var test2 = GetEntity(vm2);
            Console.WriteLine(JsonSerializer.Serialize(test2));
        }

        public static T GetEntity<T,S>(IBaseCrudVM<T,S> vm) where T: TopBasePoco<S>
        {
            return vm.Entity;
        }

        #endregion

        #region advanced

        public static void Advanced() 
        {
            IEnumerable<DerivedClass> test = new List<DerivedClass>();
            IEnumerable<BaseClass> test2 = test;

            //List<DerivedClass> list1 = new List<DerivedClass>();
            //List<BaseClass> list2 = list1;
            //IAbc<BaseClass, BaseClass> abc1 = null;
            //IAbc<DerivedClass, DerivedClass> abc2 = abc1;
            School s = new School();
            s.ID = "111";

            Major m = new Major();
            m.ID = 2;

            SchoolCRUDVM vm = new SchoolCRUDVM();
            vm.Entity = s;
            vm.DoDelete();

            MajorCRUDVM vm2 = new MajorCRUDVM();
            vm2.Entity = m;

            var t1 = GetEntity2(vm);
            Console.WriteLine(JsonSerializer.Serialize(t1));

            //var t2 = GetEntity2(vm2);
            //Console.WriteLine(JsonSerializer.Serialize(t2));
        }
        public static object GetEntity2(object vm)
        {
            BaseCRUDVM<School, string> test = null;
            IBaseCrudVM<TopBasePoco<string>, string> test2 = null;
            test2 = test;


            var t = vm as IBaseCrudVM<TopBasePoco<string>, string>;
            return t.Entity;
        }

        #endregion
    }

}
